Skip to content

Report offending input in register error messages - #1095

Open
jaewonyun1234 wants to merge 1 commit into
pasqal-io:developfrom
jaewonyun1234:error-messages-register
Open

Report offending input in register error messages#1095
jaewonyun1234 wants to merge 1 commit into
pasqal-io:developfrom
jaewonyun1234:error-messages-register

Conversation

@jaewonyun1234

Copy link
Copy Markdown
Contributor

Same as #1094, applied to base_register.py.

Nine messages updated: __init__, _init_kwargs, find_indices,
from_coordinates, four in _validate_layout, and define_detuning_map.

Also fixed a missing space that printed as Label length (3) does notmatch number of coordinates (2).

I left "Cannot create a Register with an empty qubit dictionary." alone. The
dictionary is empty, so there's nothing to print.

One thing I noticed: trap_coords[trap_id] on line 229 isn't bounds checked, so
a bad trap id gives a numpy error instead of a Pulser one.

>>> Register(qubits, layout=layout, trap_ids=(0, 99))
IndexError: index 99 is out of bounds for axis 0 with size 4

RegisterLayout.define_register catches this but the Register constructor
skips that check. I didn't fix it here since it changes behaviour, not wording.

Partially addresses #1057.

Adds the failing input to the 9 validation errors in base_register.py that previously stated only the rule, following the pattern from pasqal-io#1094. Existing message text is kept intact and details appended, so all match= assertions in tests/ continue to pass without modification. Also fixes a missing space in the label-length message, which rendered as 'does notmatch'. Partially addresses pasqal-io#1057.
@jaewonyun1234

Copy link
Copy Markdown
Contributor Author

Hi @a-corni ready for review whenever you have time.

For the trap_ids bounds check I mentioned at the bottom — happy to fold a fix
into this PR, or open it as a separate issue. Whichever you prefer.

@a-corni a-corni left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jaewonyun1234 !
I have some comments, notably on the use of sorted. You can modify some error messages if you want.
Regarding the missing check on _validate_layout. I think you are right, and I suggest we make a call to register_layout.define_register to check the inputs properly.

raise ValueError(
"If specifying 'kwargs', they must only be 'layout' and "
"'trap_ids'."
f"'trap_ids'; got {sorted(kwargs)}."

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure the sorted is needed here. Since the target of this message is a software developer, I would rather return the kwargs in the order the program submitted them.

f"Label length ({len(labels)}) does not"
f"match number of coordinates ({len(coords_)})"
f"Label length ({len(labels)}) does not "
f"match number of coordinates ({len(coords_)})."

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe report the two offending inputs: "Got coords {coords} and labels {labels}.".

Comment on lines 217 to +220
raise ValueError(
"The RegisterLayout dimensionality is not the same as this "
"register's."
f"register's; layout is {register_layout.dimensionality}D "
f"and register is {self.dimensionality}D."

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what matters is knowing the input layout
. The information you are bringing has value, you can modify the error raised:
"The RegisterLayout dimensionality ({register_layout.dimensionality}D) is not the same as this "
f"register's ({self.dimensionality}D); Got layout {register_layout} on register {self.register}."

"The IDs list must be selected among the IDs of the register's"
" qubits."
" qubits; "
f"{sorted(set(id_list) - set(self.qubit_ids))} not in "

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the sorted is necessary here, and I would suggest to take it out as it might take unnecessary time to raise this error.

)
if len(set(trap_ids)) != len(trap_ids):
raise ValueError("Every 'trap_id' must be a unique integer.")
repeated = sorted({t for t in trap_ids if trap_ids.count(t) > 1})

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be best to try to return the repeating elements in their order of appearance in the trap_ids. Therefore, I suggest to get rid of sorted, and use collections.Counter (offers a faster one-liner than your current solution)

Suggested change
repeated = sorted({t for t in trap_ids if trap_ids.count(t) > 1})
repeated = [t for t, freq in Counter(trap_ids).items() if freq > 1]

Comment on lines 231 to +233
"The amount of 'trap_ids' must be equal to the number of atoms"
" in the register."
f" in the register; got {len(trap_ids)} trap_ids "
f"for {len(self._ids)} atoms."

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can modify the returned message to show the length of trap_ids and self._ids, but what matters is returning the incorrect input:
f"The amount of 'trap_ids' {len(trap_ids)} is not equal to the number of atoms {len(self._ids)}. Got trap ids {trap_ids} for atoms {self._ids}."

"The qubit ids linked to detuning weights have to be defined"
" in the register."
" in the register. Got "
f"{sorted(set(detuning_weights) - set(self.qubit_ids))}, "

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here as well, I don't think the sorted is necessary and suggest to take it of, for the sake of time.

Comment on lines 236 to 238
for reg_coord, trap_id in zip(
self._coords_arr.as_array(detach=True), trap_ids
):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, it is missing a check that the provided trap_ids are a subset of register_layout.traps_dict(). You could do register_layout.define_register(*trap_ids, qubit_ids=list(self.qubits)) to get all the checks from RegisterLayout.defin_register. You can include this test here, and properly test it in the tests, I would be fine with this. Otherwise, we can create a separate issue and tackle it separately, later. Let me know what you prefer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants